package com.central.apps.handler.project;

import com.central.app.common.base.BaseHandler;
import com.central.app.service.HandlerService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 处理项目成本结构业务逻辑
 *
 * @author lidachao
 * @date 2023/1/30
 */
@Component
@Slf4j
public class ProjectCostStructureHandler extends BaseHandler {

    @Autowired
    private HandlerService handlerService;

    @Override
    public String validateSave(String app, String objName, Map<String, Object> data) throws Exception {
        // 校验成本要素对应的预算类别金额是否超出预算申请预算类别金额
        if ("gq_procoststructure".equals(objName)) {
            Object object = MapUtils.getObject(data, "TableUKey84080ChangeData");
            if (object == null) {
                object = MapUtils.getObject(data, "TableUKey84080");
            }

            if (object != null) {
                Integer proId = MapUtils.getInteger(data, "proid");
                List<Map<String, Object>> childList = (List<Map<String, Object>>) object;
                // 存储临时数据
                Map<String, BigDecimal> tempMap = new HashMap<>();
                StringBuilder ids = new StringBuilder();
                List<Integer> bcIds = new ArrayList<>();
                Map<String, String> bcDescs = new HashMap<>();

                // 循环存储预算类别对应的金额
                for (Map<String, Object> childMap : childList) {
                    Integer id = MapUtils.getInteger(childMap, "id");
                    Integer bcId = MapUtils.getInteger(childMap, "bcid");
                    String bcDesc = MapUtils.getString(childMap, "bcdesc");
                    String budgetAmt = MapUtils.getString(childMap, "budgetamt");
                    BigDecimal bBudgetAmt = new BigDecimal(budgetAmt);

                    if (tempMap.containsKey(bcId.toString())) {
                        BigDecimal tempBudgetAmt = tempMap.get(bcId.toString());
                        tempMap.put(bcId.toString(), tempBudgetAmt.add(bBudgetAmt));
                    } else {
                        tempMap.put(bcId.toString(), bBudgetAmt);
                    }

                    bcIds.add(bcId);
                    bcDescs.put(bcId.toString(), bcDesc);
                    ids.append(id).append(",");
                }

                ids.deleteCharAt(ids.length() - 1);

                // 循环比较是否超出预算
                StringBuilder promptStr = new StringBuilder();
                for (Integer bcId : bcIds) {
                    BigDecimal tBudgetAmt = BigDecimal.ZERO;
                    List<Map<String, Object>> sumList = handlerService.findBySql("select sum(budgetamt) as budgetamt from gq_procostelements where proid = " + proId + " and bcid = "
                            + bcId + " and id not in (" + ids + ") group by bcdesc");

                    if (CollectionUtils.isNotEmpty(sumList)) {
                        Map<String, Object> sumMap = sumList.get(0);
                        String budgetAmt = MapUtils.getString(sumMap, "budgetamt");
                        tBudgetAmt = new BigDecimal(budgetAmt);
                    }

                    if (tempMap.containsKey(bcId.toString())) {
                        BigDecimal tempBudgetAmt = tempMap.get(bcId.toString());
                        tBudgetAmt = tBudgetAmt.add(tempBudgetAmt);
                    }

                    List<Map<String, Object>> list = handlerService.findBySql("select budgetamt from gq_pbcategory where status = '已批准' and proid = " + proId + " and bcid = " + bcId);
                    if (CollectionUtils.isEmpty(list)) {
                        return "预算申请未申请" + bcDescs.get(bcId.toString()) + "预算类别预算!";
                    }
                    Map<String, Object> map = list.get(0);
                    String pbBudgetAmt = MapUtils.getString(map, "budgetamt");
                    BigDecimal bPbBudgetAmt = new BigDecimal(pbBudgetAmt);

                    if (tBudgetAmt.compareTo(bPbBudgetAmt) > 0) {
                        promptStr.append(bcDescs.get(bcId.toString())).append(",");
                    }
                }

                if (StringUtils.isNotEmpty(promptStr.toString())) {
                    promptStr.deleteCharAt(promptStr.length() - 1);
                    promptStr.append("等预算类别成本预算金额不能大于预算类别预算金额!");
                    return promptStr.toString();
                }
            }
        }

        return null;
    }

    @Override
    public void afterSave(String app, String objName, Map<String, Object> data, boolean isUpdate) throws Exception {
        // 保存项目成本要素信息后
        if ("gq_procostelements".equals(objName)) {
            Integer pcsid = MapUtils.getInteger(data, "pcsid");
            Integer proid = MapUtils.getInteger(data, "proid");

            // 统计成本结构子级总计成本
            List<Map<String, Object>> list = handlerService.findBySql("select ifnull(sum(budgetamt), 0) as totalCost from gq_procostelements where proid = " + proid + " and pcsid = " + pcsid);
            Map<String, Object> map = list.get(0);
            Double totalCost = MapUtils.getDouble(map, "totalCost");

            // 更新成本结构成本总计
            handlerService.updateBySql("update gq_procoststructure set totalcost = " + totalCost + ",budgetamt = " + totalCost + " where proid = " + proid + " and id = " + pcsid);

            // 向上递归统计成本结构成本总计
            recursiveStatistics(proid, pcsid);
        }
    }

    /**
     * 递归查询并统计树形父级数据
     *
     * @param proid
     * @param pcsid
     */
    private void recursiveStatistics(Integer proid, Integer pcsid) throws Exception {
        // 查询父级成本结构
        List<Map<String, Object>> list = handlerService.findBySql("select parentid from gq_procoststructure where proid = " + proid + " and id = " + pcsid);

        if (CollectionUtils.isNotEmpty(list)) {
            Map<String, Object> map = list.get(0);
            Integer parentid = MapUtils.getInteger(map, "parentid");

            if (parentid != null) {
                // 查询子级成本结构汇总成本
                list = handlerService.findBySql("select ifnull(sum(budgetamt), 0) as totalCost from gq_procoststructure where proid = " + proid + " and parentid = " + parentid);
                map = list.get(0);
                Double totalCost = MapUtils.getDouble(map, "totalCost");

                // 更新成本结构成本总计
                handlerService.updateBySql("update gq_procoststructure set totalcost = " + totalCost + ",budgetamt = " + totalCost + " where proid = " + proid + " and id = " + parentid);

                // 向上递归统计成本结构成本总计
                recursiveStatistics(proid, parentid);
            }
        }
    }
}
